/**
 * Trabajo de Ingeniería de Software 2
 * Año 2008
 * Sistema de Reserva de Recursos.
 * Desarrolladores: - Marcelo Ferreira.
 *                  - Christian Gómez.
 *                  - Marcelo Rodas.
 */
package controller;

import java.util.List;
import java.util.Map;
import javax.annotation.Resource;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.model.SelectItem;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.PersistenceUnit;
import javax.persistence.Query;
import javax.faces.application.FacesMessage;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import javax.faces.FacesException;
import java.util.HashMap;
import javax.faces.validator.ValidatorException;
import javax.transaction.UserTransaction;
import modelo.Datospersonales;
import modelo.Rol;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Vector;
import javax.servlet.http.HttpSession;
import modelo.Solicitudreserva;
import modelo.Usuario;

/**
 * Controlador de las Funcionalidades de una Usuario.
 * Utilizado para manejar la capa de controlador (MVC)
 * del sistema.
 * @author cgomez
 * @version 1.0
 */
public class UsuarioController {
    
    // POJO de Usuario Representada.
    private Usuario usuario = null;
    // Lista de Usuarios
    private List<Usuario> usuarios = null;
    // Transacción del usuario.
    @Resource
    private UserTransaction utx = null;
    // Administrador de la Persistencia de los Usuario.
    // Relaciona al Controlador con el Modelo (MVC)
    @PersistenceUnit(unitName = "sistemaReservaPU")
    private EntityManagerFactory emf = null;
    //variable que contiene la confirmacion de contraseña
    private String confcontrasenha;
    /**
     * Getter del Administrador de Entidades.
     * @return EntityManager
     */
    public EntityManager getEntityManager() {
        return emf.createEntityManager();
    }
    // ---------- Variables para paginar en el jsp -------------
    // variable auxiliar que indica el tamaño de conjunto
    public int batchSize = 100;
    // variable auxiliar para indicar el 1er elemento
    private int firstItem = 0;
    // variable auxiliar utilizado como contador de elementos
    private int itemCount = -1;
    // variable auxiliar utilizado como parte del dia de una fecha

    /**
     * Setter del Usuario de los Solicitudes de Reserva
     * @param solicitudreservaCollection coleccion de solicitureserva
     */    
    public void setSolicitudreservaCollectionOfUsuario(Solicitudreserva[] solicitudreservaCollection) {
        List<Solicitudreserva> solicitudreservaCollectionList = Arrays.asList(solicitudreservaCollection);
        usuario.setSolicitudreservaCollection(solicitudreservaCollectionList);
    }
    
    /**
     * Getter del Usuario de los SolicitudReserva
     * @return colleccion de Solicitudreserva
     */
    public Solicitudreserva[] getSolicitudreservaCollectionOfUsuario() {
        Collection<Solicitudreserva> solicitudreservaCollection = usuario.getSolicitudreservaCollection();
        if (solicitudreservaCollection == null) {
            return new Solicitudreserva[0];
        }
        return solicitudreservaCollection.toArray(new Solicitudreserva[0]);
    }
    
    /**
     * Metodo para obtener una lista de los Usruarios disponibles de varias selecciones
     * @return lista de DatosPersonales
     */
    public SelectItem[] getUsuariosAvailableSelectMany() {
        return getUsuariosAvailable(false);
    }
    
    /**
     * Metodo publico para obtener una lista de los Usuarios disponibles de una sola seleccion
     * @return lista de DatosPersonales
     */
    public SelectItem[] getUsuariosAvailableSelectOne() {
        return getUsuariosAvailable(true);
    }
    
    /**
     * Metodo privado para obtener una lista de los Usuarios disponibles de una sola seleccion
     * @return lista de Usuarios
     */
    private SelectItem[] getUsuariosAvailable(boolean one) {
        List<Usuario> allUsuarios = getUsuarios(true);
        int size = one ? allUsuarios.size() + 1 : allUsuarios.size();
        SelectItem[] items = new SelectItem[size];
        int i = 0;
        if (one) {
            items[0] = new SelectItem("", "---");
            i++;
        }
        for (Usuario x : allUsuarios) {
            items[i++] = new SelectItem(x, x.toString());
        }
        return items;
    }
    
    /**
     * Metodo para obtener el objeto Usuario del Request
     * @return el objeto Usuario obtenido
     */
    public Usuario getUsuario() {
        if (usuario == null) {
            usuario = getUsuarioFromRequest();
        }
        if (usuario == null) {
            usuario = new Usuario();
        }
        return usuario;
    }
    
    /**
     * Metodo para resetear los valores de inicio y llamar al Tag de Lista de Usuarios
     * @return el tag de la Lista de Usuarios
     */
    public String listSetup() {
        reset(true);
        return "usuario_list";
    }
    
    /**
     * Metodo para inicializar los valores del Objeto Usuario para un nuevo objeto
     * @return el Tag del JSP para crear una nueva entrada de Usuario
     */
    public String createSetup() {
        reset(false);
        usuario = new Usuario();
        return "usuario_create";
    }
    
    /**
     * Metodo que retorga el tag de la pagina principal
     * @return Strig
     */
    public String principalSetup() {
        return "principalSetup";
    }
    
    /**
     * Metodo publico para crear una nueva entrada de Usuario
     * @return el Tag del siguiente JSP a desplegar
     */
    public String create() {
        if (usuario.getSolicitudreservaCollection() == null) {
            usuario.setSolicitudreservaCollection(new ArrayList<Solicitudreserva>());
        }
        EntityManager em = getEntityManager();
        try {
            if (!usuario.getContrasenha().equals(this.getConfcontrasenha())) {
                addErrorMessage("La nueva contraseña y la confirmación no coinciden.");
                return null;
            }else if(this.getConfcontrasenha().length()<5){
                addErrorMessage("La nueva contraseña debe tener al menos 5 caracteres.");
                return null;
            }
            utx.begin();
            Datospersonales iddatospersonales = usuario.getIddatospersonales();
            if (iddatospersonales != null) {
                iddatospersonales = em.getReference(iddatospersonales.getClass(), iddatospersonales.getIddatospersonales());
                usuario.setIddatospersonales(iddatospersonales);
            }
            Rol idRol = usuario.getIdRol();
            if (idRol != null) {
                idRol = em.getReference(idRol.getClass(), idRol.getIdRol());
                usuario.setIdRol(idRol);
            }
            List<Solicitudreserva> attachedSolicitudreservaCollection = new ArrayList<Solicitudreserva>();
            for (Solicitudreserva solicitudreservaCollectionSolicitudreservaToAttach : usuario.getSolicitudreservaCollection()) {
                solicitudreservaCollectionSolicitudreservaToAttach = em.getReference(solicitudreservaCollectionSolicitudreservaToAttach.getClass(), solicitudreservaCollectionSolicitudreservaToAttach.getIdSolicitudReserva());
                attachedSolicitudreservaCollection.add(solicitudreservaCollectionSolicitudreservaToAttach);
            }
            usuario.setSolicitudreservaCollection(attachedSolicitudreservaCollection);
            em.persist(usuario);
            if (iddatospersonales != null) {
                iddatospersonales.getUsuarioCollection().add(usuario);
                iddatospersonales = em.merge(iddatospersonales);
            }
            if (idRol != null) {
                idRol.getUsuarioCollection().add(usuario);
                idRol = em.merge(idRol);
            }
            for (Solicitudreserva solicitudreservaCollectionSolicitudreserva : usuario.getSolicitudreservaCollection()) {
                Usuario oldIdSolicitanteOfSolicitudreservaCollectionSolicitudreserva = solicitudreservaCollectionSolicitudreserva.getIdSolicitante();
                solicitudreservaCollectionSolicitudreserva.setIdSolicitante(usuario);
                solicitudreservaCollectionSolicitudreserva = em.merge(solicitudreservaCollectionSolicitudreserva);
                if (oldIdSolicitanteOfSolicitudreservaCollectionSolicitudreserva != null) {
                    oldIdSolicitanteOfSolicitudreservaCollectionSolicitudreserva.getSolicitudreservaCollection().remove(solicitudreservaCollectionSolicitudreserva);
                    oldIdSolicitanteOfSolicitudreservaCollectionSolicitudreserva = em.merge(oldIdSolicitanteOfSolicitudreservaCollectionSolicitudreserva);
                }
            }
            utx.commit();
            addSuccessMessage("El usuario fue creado exitosamente.");
        } catch (Exception ex) {
            try {
                if (findUsuario(usuario.getIdUsuario()) != null) {
                    addErrorMessage("Usuario " + usuario + " ya existe.");
                } else {
                    ensureAddErrorMessage(ex, "Ha ocurrido un error de persistencia.");
                }
                utx.rollback();
            } catch (Exception e) {
                ensureAddErrorMessage(e, "Ha ocurrido un error al intentar hacer una operacion de deshace la transacción.");
            }
            return null;
        } finally {
            em.close();
        }
        return listSetup();
    }
    
    /**
     * Funcion de Navegacion a la Pagina Detail.jsp de los Usuarios
     * @return String
     */
    public String detailSetup() {
        return scalarSetup("usuario_detail");
    }
    
    /**
     * Funcion de Navegacion a la Pagina DetailSolicitante.jsp de los Usuario Solicitantes
     * @return String
     */    
    public String detailSetupSolicitante() {
        return scalarSetup("usuarioSolicitante_detail");
    }
    
    /**
     * Funcion de Navegacion a la Pagina Edit.jsp de los Usuario's
     * @return String
     */    
    public String editSetup() {
        return scalarSetup("usuario_edit");
    }
    
    /**
     * Funcion de Navegacion a la Pagina EditSolicitante.jsp de los Usuario's Solicitantes
     * @return String
     */    
    public String editSetupSolicitante() {
        return scalarSetup("usuarioSoliciante_edit");
    }
    
    /*
     * Función de Navegación General, controla si existe la ruta de
     * navegación.
     */
    private String scalarSetup(String destination) {
        reset(false);
        usuario = getUsuarioFromRequest();
        this.setConfcontrasenha(this.usuario.getContrasenha());
        if (usuario == null) {
            String requestUsuarioString = getRequestParameter("jsfcrud.currentUsuario");
            addErrorMessage("El usuario con el id " + requestUsuarioString + " ya no existe en la base de datos.");
            String relatedControllerOutcome = relatedControllerOutcome();
            if (relatedControllerOutcome != null) {
                return relatedControllerOutcome;
            }
            return listSetup();
        }
        HttpSession session = (HttpSession) FacesContext.getCurrentInstance().getExternalContext().getSession(false);
        Usuario user = (Usuario) session.getAttribute("user");
        usuario.setUserAudita(user.getIdUsuario());
        return destination;
    }
    
    /**
     * Función privada que procesa los cambios realizados sobre los
     * Usuario's Representados.
     * @return String
     */
    public String editar() {
        UsuarioConverter converter = new UsuarioConverter();
        String usuarioString = converter.getAsString(FacesContext.getCurrentInstance(), null, usuario);
        String currentUsuarioString = getRequestParameter("jsfcrud.currentUsuario");
        if (usuarioString == null || usuarioString.length() == 0 || !usuarioString.equals(currentUsuarioString)) {
            String outcome = editSetup();
            if ("usuario_edit".equals(outcome)) {
                addErrorMessage("No se puede editar el usuario. Intente nuevamente.");
            }
            return outcome;
        }
        EntityManager em = getEntityManager();
        try {
            if (!usuario.getContrasenha().equals(this.getConfcontrasenha())) {
                addErrorMessage("La nueva contraseña y la confirmación no coinciden.");
                return null;
            }else if(this.getConfcontrasenha().length()<5){
                addErrorMessage("La nueva contraseña debe tener al menos 5 caracteres.");
                return null;
            }
            utx.begin();
            Usuario persistentUsuario = em.find(Usuario.class, usuario.getIdUsuario());
            Datospersonales iddatospersonalesOld = persistentUsuario.getIddatospersonales();
            Datospersonales iddatospersonalesNew = usuario.getIddatospersonales();
            Rol idRolOld = persistentUsuario.getIdRol();
            Rol idRolNew = usuario.getIdRol();
            Collection<Solicitudreserva> solicitudreservaCollectionOld = persistentUsuario.getSolicitudreservaCollection();
            Collection<Solicitudreserva> solicitudreservaCollectionNew = usuario.getSolicitudreservaCollection();
            if (iddatospersonalesNew != null) {
                iddatospersonalesNew = em.getReference(iddatospersonalesNew.getClass(), iddatospersonalesNew.getIddatospersonales());
                usuario.setIddatospersonales(iddatospersonalesNew);
            }
            if (idRolNew != null) {
                idRolNew = em.getReference(idRolNew.getClass(), idRolNew.getIdRol());
                usuario.setIdRol(idRolNew);
            }
            List<Solicitudreserva> attachedSolicitudreservaCollectionNew = new ArrayList<Solicitudreserva>();
            for (Solicitudreserva solicitudreservaCollectionNewSolicitudreservaToAttach : solicitudreservaCollectionNew) {
                solicitudreservaCollectionNewSolicitudreservaToAttach = em.getReference(solicitudreservaCollectionNewSolicitudreservaToAttach.getClass(), solicitudreservaCollectionNewSolicitudreservaToAttach.getIdSolicitudReserva());
                attachedSolicitudreservaCollectionNew.add(solicitudreservaCollectionNewSolicitudreservaToAttach);
            }
            solicitudreservaCollectionNew = attachedSolicitudreservaCollectionNew;
            usuario.setSolicitudreservaCollection(solicitudreservaCollectionNew);
            usuario = em.merge(usuario);
            if (iddatospersonalesOld != null && !iddatospersonalesOld.equals(iddatospersonalesNew)) {
                iddatospersonalesOld.getUsuarioCollection().remove(usuario);
                iddatospersonalesOld = em.merge(iddatospersonalesOld);
            }
            if (iddatospersonalesNew != null && !iddatospersonalesNew.equals(iddatospersonalesOld)) {
                iddatospersonalesNew.getUsuarioCollection().add(usuario);
                iddatospersonalesNew = em.merge(iddatospersonalesNew);
            }
            if (idRolOld != null && !idRolOld.equals(idRolNew)) {
                idRolOld.getUsuarioCollection().remove(usuario);
                idRolOld = em.merge(idRolOld);
            }
            if (idRolNew != null && !idRolNew.equals(idRolOld)) {
                idRolNew.getUsuarioCollection().add(usuario);
                idRolNew = em.merge(idRolNew);
            }
            for (Solicitudreserva solicitudreservaCollectionOldSolicitudreserva : solicitudreservaCollectionOld) {
                if (!solicitudreservaCollectionNew.contains(solicitudreservaCollectionOldSolicitudreserva)) {
                    solicitudreservaCollectionOldSolicitudreserva.setIdSolicitante(null);
                    solicitudreservaCollectionOldSolicitudreserva = em.merge(solicitudreservaCollectionOldSolicitudreserva);
                }
            }
            for (Solicitudreserva solicitudreservaCollectionNewSolicitudreserva : solicitudreservaCollectionNew) {
                if (!solicitudreservaCollectionOld.contains(solicitudreservaCollectionNewSolicitudreserva)) {
                    Usuario oldIdSolicitanteOfSolicitudreservaCollectionNewSolicitudreserva = solicitudreservaCollectionNewSolicitudreserva.getIdSolicitante();
                    solicitudreservaCollectionNewSolicitudreserva.setIdSolicitante(usuario);
                    solicitudreservaCollectionNewSolicitudreserva = em.merge(solicitudreservaCollectionNewSolicitudreserva);
                    if (oldIdSolicitanteOfSolicitudreservaCollectionNewSolicitudreserva != null && !oldIdSolicitanteOfSolicitudreservaCollectionNewSolicitudreserva.equals(usuario)) {
                        oldIdSolicitanteOfSolicitudreservaCollectionNewSolicitudreserva.getSolicitudreservaCollection().remove(solicitudreservaCollectionNewSolicitudreserva);
                        oldIdSolicitanteOfSolicitudreservaCollectionNewSolicitudreserva = em.merge(oldIdSolicitanteOfSolicitudreservaCollectionNewSolicitudreserva);
                    }
                }
            }
            utx.commit();
            addSuccessMessage("El usuario fue actualizado exitosamente.");
        } catch (Exception ex) {
            try {
                String msg = ex.getLocalizedMessage();
                if (msg != null && msg.length() > 0) {
                    addErrorMessage(msg);
                } else if (getUsuarioFromRequest() == null) {
                    addErrorMessage("El usuario con el id " + currentUsuarioString + " ya no exite.");
                    utx.rollback();
                    return listSetup();
                } else {
                    addErrorMessage("Ha ocurrido un error de persistencia en la base de datos.");
                }
                utx.rollback();
            } catch (Exception e) {
                ensureAddErrorMessage(e, "A ocurrido un error al intentar deshacer la operacion en la base de datos.");
            }
            return null;
        } finally {
            em.close();
        }
        return listSetup();
    }

    /**
     * Función publica que procesa los cambios realizados sobre los
     * Usuario's Representados.
     * @return String
     */
    public String edit(){
        return editar();
    }
    
    /**
     * Función publica que procesa los cambios realizados sobre los
     * Usuario's Solicitantes de cada propietario.
     * @return String
     */
    public String editSolicitante(){
        String resultado = editar();
        if (resultado == null)
            return null;
        else if (resultado.equals("usuario_edit"))
            return resultado;
        else
            return "usuarioSolicitante_list";
    }
    
    /**
     * Funcion que permite la eliminacion de una entrada de Usuario's
     * @return String
     */    
    public String destroy() {
        usuario = getUsuarioFromRequest();
        if (usuario == null) {
            String currentUsuarioString = getRequestParameter("jsfcrud.currentUsuario");
            addErrorMessage("El usuario con el id " + currentUsuarioString + " ya no existe.");
            String relatedControllerOutcome = relatedControllerOutcome();
            if (relatedControllerOutcome != null) {
                return relatedControllerOutcome;
            }
            return listSetup();
        }
        EntityManager em = getEntityManager();
        try {
            utx.begin();
            usuario = em.getReference(usuario.getClass(), usuario.getIdUsuario());
            Datospersonales iddatospersonales = usuario.getIddatospersonales();
            if (iddatospersonales != null) {
                iddatospersonales.getUsuarioCollection().remove(usuario);
                iddatospersonales = em.merge(iddatospersonales);
            }
            Rol idRol = usuario.getIdRol();
            if (idRol != null) {
                idRol.getUsuarioCollection().remove(usuario);
                idRol = em.merge(idRol);
            }
            Collection<Solicitudreserva> solicitudreservaCollection = usuario.getSolicitudreservaCollection();
            for (Solicitudreserva solicitudreservaCollectionSolicitudreserva : solicitudreservaCollection) {
                solicitudreservaCollectionSolicitudreserva.setIdSolicitante(null);
                solicitudreservaCollectionSolicitudreserva = em.merge(solicitudreservaCollectionSolicitudreserva);
            }
            em.remove(usuario);
            utx.commit();
            addSuccessMessage("Usuario was successfully deleted.");
        } catch (Exception ex) {
            try {
                ensureAddErrorMessage(ex, "A persistence error occurred.");
                utx.rollback();
            } catch (Exception e) {
                ensureAddErrorMessage(e, "An error occurred attempting to roll back the transaction.");
            }
            return null;
        } finally {
            em.close();
        }
        String relatedControllerOutcome = relatedControllerOutcome();
        if (relatedControllerOutcome != null) {
            return relatedControllerOutcome;
        }
        return listSetup();
    }
    
    /**
     * Función privada para obtener el Objeto Usuario del Request.
     * @return Usuario
     */
    private Usuario getUsuarioFromRequest() {
        String theId = getRequestParameter("jsfcrud.currentUsuario");
        return (Usuario) new UsuarioConverter().getAsObject(FacesContext.getCurrentInstance(), null, theId);
    }

    /**
     * Función para obtener un valor del request.
     * @param key
     * @return String
     */
    private String getRequestParameter(String key) {
        return FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get(key);
    }
    
    /**
     * Getter de Usuario's (atributo local).
     * @return List<Usuario>
     */
    public List<Usuario> getUsuarios() {
        if (usuarios == null) {
            usuarios = getUsuarios(false);
        }
        return usuarios;
    }
    
    /**
     * Getter de todos los objetos Usuario (de la Base de Datos)
     * @param all
     * @return List<Usuario>
     */
    public List<Usuario> getUsuarios(boolean all) {
        EntityManager em = getEntityManager();
        try {
            //Recuperar el ROL del usuario
            HttpSession session = (HttpSession) FacesContext.getCurrentInstance().getExternalContext().getSession(false);
            Usuario usuarioLogeado = (Usuario) session.getAttribute("user");
            
            String SQL= "select f_recuperar_rol('"+usuarioLogeado.getIdUsuario()+"')";
            Query q = em.createNativeQuery(SQL);
            Vector v = new Vector();
            v  = (Vector) q.getSingleResult();
            String rol = (String)v.get(0);
            //Si el rol es solicitante, solo recupera el resgitro del solicituante
            if (rol.equals("4")) {
                q = em.createQuery("select object(o) from Usuario as o where o.idUsuario like '"+usuarioLogeado.getIdUsuario()+"'");
            }
            else{
                q = em.createQuery("select object(o) from Usuario as o ");
            }
            if (!all) {
                q.setMaxResults(batchSize);
                q.setFirstResult(getFirstItem());
            }
            return q.getResultList();
        } finally {
            em.close();
        }
    }
    
    /*
     *-------------------------------------------------------------------
     * Funciones de manejo de Mensajes y Errores.
     *-------------------------------------------------------------------
     */
    
    /**
     * Asegura que se almacenen los errores
     * @param ex
     * @param defaultMsg
     */
    private void ensureAddErrorMessage(Exception ex, String defaultMsg) {
        String msg = ex.getLocalizedMessage();
        if (msg != null && msg.length() > 0) {
            addErrorMessage(msg);
        } else {
            addErrorMessage(defaultMsg);
        }
    }
    
    /**
     * Agrega mensajes de Error para la Página. 
     * @param msg
     */

    public static void addErrorMessage(String msg) {
        FacesMessage facesMsg = new FacesMessage(FacesMessage.SEVERITY_ERROR, msg, msg);
        FacesContext.getCurrentInstance().addMessage(null, facesMsg);
    }
    
    /**
     * Agrega mensajes de Exito para la Página.
     * @param msg
     */
    public static void addSuccessMessage(String msg) {
        FacesMessage facesMsg = new FacesMessage(FacesMessage.SEVERITY_INFO, msg, msg);
        FacesContext.getCurrentInstance().addMessage("successInfo", facesMsg);
    }
    
    /**
     * Obtiene un Objeto Usuario con el id correspondiente.
     * @param id idUsuario
     * @return Objeto Usuario
     */
    public Usuario findUsuario(String id) {
        EntityManager em = getEntityManager();
        try {
            Usuario o = (Usuario) em.find(Usuario.class, id);
            return o;
        } finally {
            em.close();
        }
    }
    
    /**
     * ------------------------------------------
     * Funciones de Iteración
     * ------------------------------------------
     */
    
    /**
     * Funcion para obtener una cuenta de todos los items de esta clase
     * @return int
     */
    public int getItemCount() {
        if (itemCount == -1) {
            EntityManager em = getEntityManager();
            try {
                itemCount = ((Long) em.createQuery("select count(o) from Usuario as o").getSingleResult()).intValue();
            } finally {
                em.close();
            }
        }
        return itemCount;
    }
    
    /**
     * Funcion para obtener el primer item de esta clase
     * @return int
     */
    public int getFirstItem() {
        getItemCount();
        if (firstItem >= itemCount) {
            if (itemCount == 0) {
                firstItem = 0;
            } else {
                int zeroBasedItemCount = itemCount - 1;
                double pageDouble = zeroBasedItemCount / batchSize;
                int page = (int) Math.floor(pageDouble);
                firstItem = page * batchSize;
            }
        }
        return firstItem;
    }
    
    /**
     * Funcion para obtener el ultimo item de esta clase
     * @return int
     */
    public int getLastItem() {
        getFirstItem();
        return firstItem + batchSize > itemCount ? itemCount : firstItem + batchSize;
    }
    /**
     * Funcion para obtener el tamaño de datos a desplegar de esta clase
     * @return int
     */
    public int getBatchSize() {
        return batchSize;
    }
    
    /**
     * Funcion para obtener el siguiente item de esta clase
     * @return int
     */
    public String next() {
        reset(false);
        getFirstItem();
        if (firstItem + batchSize < itemCount) {
            firstItem += batchSize;
        }
        return "usuario_list";
    }
    
    /**
     * Funcion para obtener el item anterior de esta clase
     * @return int
     */
    public String prev() {
        reset(false);
        getFirstItem();
        firstItem -= batchSize;
        if (firstItem < 0) {
            firstItem = 0;
        }
        return "usuario_list";
    }
    
    /**
     * Funcion para saber de que contexto esta viniendo la peticion
     * @return String
     */
    private String relatedControllerOutcome() {
        String relatedControllerString = getRequestParameter("jsfcrud.relatedController");
        String relatedControllerTypeString = getRequestParameter("jsfcrud.relatedControllerType");
        if (relatedControllerString != null && relatedControllerTypeString != null) {
            FacesContext context = FacesContext.getCurrentInstance();
            Object relatedController = context.getApplication().getELResolver().getValue(context.getELContext(), null, relatedControllerString);
            try {
                Class<?> relatedControllerType = Class.forName(relatedControllerTypeString);
                Method detailSetupMethod = relatedControllerType.getMethod("detailSetup");
                return (String) detailSetupMethod.invoke(relatedController);
            } catch (ClassNotFoundException e) {
                throw new FacesException(e);
            } catch (NoSuchMethodException e) {
                throw new FacesException(e);
            } catch (IllegalAccessException e) {
                throw new FacesException(e);
            } catch (InvocationTargetException e) {
                throw new FacesException(e);
            }
        }
        return null;
    }
    
    /**
     * Borra la referencia al objeto Representado (Borrado sin persistencia).
     * @param resetFirstItem
     */
    private void reset(boolean resetFirstItem) {
        usuario = null;
        usuarios = null;
        itemCount = -1;
        if (resetFirstItem) {
            firstItem = 0;
        }
    }
    
    private Map<Object, String> asString = null;
    /**
     * Mapea el tipo de Objeto a un tipo String
     * @return Map<Object, String>
     */
    public Map<Object, String> getAsString() {
        if (asString == null) {
            asString = new HashMap<Object, String>() {

                @Override
                public String get(Object key) {
                    if (key instanceof Object[]) {
                        Object[] keyAsArray = (Object[]) key;
                        if (keyAsArray.length == 0) {
                            return "(No Items)";
                        }
                        StringBuffer sb = new StringBuffer();
                        for (int i = 0; i < keyAsArray.length; i++) {
                            if (i > 0) {
                                sb.append("<br />");
                            }
                            sb.append(keyAsArray[i]);
                        }
                        return sb.toString();
                    }
                    return new UsuarioConverter().getAsString(FacesContext.getCurrentInstance(), null, (Usuario) key);
                }
            };
        }
        return asString;
    }
    
    /**
     * Función que Vincula y Valida JSP con el Objeto Usuario Representado.
     * @param facesContext
     * @param component
     * @param value
     */
    public void validateCreate(FacesContext facesContext, UIComponent component, Object value) {
        UsuarioConverter converter = new UsuarioConverter();
        String newUsuarioString = converter.getAsString(FacesContext.getCurrentInstance(), null, new Usuario());
        String usuarioString = converter.getAsString(FacesContext.getCurrentInstance(), null, usuario);
        if (!newUsuarioString.equals(usuarioString)) {
            createSetup();
        }
    }
    
    /**
     * metodo que obtiene la contraseña de confirmacion
     * @return String
     */
    public String getConfcontrasenha() {
        return confcontrasenha;
    }
    
    /**
     * metodo que asigna la contraseña de confirmacion a la variable
     * @param confcontrasenha contiene la contraseña a confirmar
     */
    public void setConfcontrasenha(String confcontrasenha) {
        this.confcontrasenha = confcontrasenha;
    }
    
    /**
     * Obtiene un lista de Usuarios
     * @return List<Usuario>
     */
    public List<Usuario> getUsuarios2() {
        if (usuarios == null) {
            usuarios = getUsuarios2(false);
        }
        return usuarios;
    }
    
    /**
     * Getter de todos los objetos Usuario Solicitantes(de la Base de Datos)
     * @param all
     * @return List<Usuario> solicitantes
     */
    public List<Usuario> getUsuarios2(boolean all) {
        EntityManager em = getEntityManager();
        try {
            //Recuperar el ROL del usuario
            HttpSession session = (HttpSession) FacesContext.getCurrentInstance().getExternalContext().getSession(false);
            Usuario usuarioLogeado = (Usuario) session.getAttribute("user");
            
            String SQL= "select f_recuperar_rol('"+usuarioLogeado.getIdUsuario()+"')";
            Query q = em.createNativeQuery(SQL);
            Vector v = new Vector();
            v  = (Vector) q.getSingleResult();
            String rol = (String)v.get(0);
            //Si el rol es solicitante, solo recupera el resgitro del solicituante
            if (rol.equals("3")) {
                q = em.createQuery("select object(o) from Usuario as o where o.idRol.idRol = 4");
            }
            else{
                q = em.createQuery("select object(o) from Usuario as o");
            }
            if (!all) {
                q.setMaxResults(batchSize);
                q.setFirstResult(getFirstItem());
            }
            return q.getResultList();
        } finally {
            em.close();
        }
    }
}
